home *** CD-ROM | disk | FTP | other *** search
/ Amiga News 96 / Amiga News 96.iso / amig_ad_os / laurent_faillie / lfcinter / lfcinter.cxx < prev    next >
C/C++ Source or Header  |  1977-12-31  |  9KB  |  220 lines

  1. /****************************************************************************\
  2. *  LFCInter                                                                  *
  3. *      © LFSoft 1995-96                                                      *
  4. *                                                                            *
  5. *  Interpréteur C (réduit), écrit pour qu'il soit portable...                *
  6. *                                                                            *
  7. *                   Voir le fichier de documentation                         *
  8. *                                                                            *
  9. *   .Le développement a été fait sur                                         *
  10. *   - un AMIGA 4000 (68040, 14Mo de RAM, DD 120 Mo, CD-ROM x4, WB et KS 3.0) *
  11. *   - un AMIGA 1000 (68010, 8Mo de RAM, DD 52 Mo, WB et KS 2.1)              *
  12. *   - un MicroVAXII (16 Mo de RAM, deux RD54, sous ULTRIX 4.2)               *
  13. *   en utilisant GCC 2.7.0 du CD Fresh Fish 10.                              *
  14. *                                                                            *
  15. *    La version utilisée pour la démonstration a été compilée avec le        *
  16. *   BORLAND C++ 4.52 car elle devait se faire sur un PC portable 386sx (j'ai *
  17. *   pas les moyens de m'offrir un Amiga portable, sniff).                    *
  18. *                                                                            *
  19.  ******************************  Historique *********************************
  20. *  02/12/1995  Début du développement en C.                                  *
  21. *  22/12/1995  Passage au C++ pour faciliter le traitement des chaînes.      *
  22. *  10/01/1996  Première compilation avec le BORLAND (Certaines modifications *
  23. *              ont été nécéssaires du fait que certaines #include n'ont pas  *
  24. *              le même nom, (merci le MS-DOS), et que ce compilateur est     *
  25. *              moins puissant que GCC). De plus, certaines fonctions ne      *
  26. *              correspondent pas à celle de GCC, genre les constructeurs des *
  27. *              'string'...                                                   *
  28. *                       -----------------------------------                  *
  29. *   01/04/1996  Réécriture complète pour utiliser l'objet '_token' pour la   *
  30. *               lecture des éléments du fichier source -> Décodage de la     *
  31. *               syntaxe plus simple et traitement des erreurs plus portable. *
  32. *                       -----------------------------------                  *
  33. *   29/04/1996  Première compilation sur le VAX: Modif dans                  *
  34. *               /gnu/lib/g++-include/std.h qui pause problème lorsque        *
  35. *               cstring.h est inclu (fonction const pour GCC et non const    *
  36. *               pour les includes système).                                  *
  37. *                       -----------------------------------                  *
  38. *   07/06/1996  Derniere compilation pour la présentation avec, encore,      *
  39. *               quelques corrections de buggues...                           *
  40. *                                                                            *
  41. \****************************************************************************/
  42.  
  43. #include "LFCInter.h"
  44. #include "Token.h"
  45. #include "LFDStack.h"
  46. #include "LFCI_Cal.h"
  47. #include <fstream.h>
  48.  
  49. #ifdef __BCPLUSPLUS__
  50. extern unsigned _stklen = (unsigned) 40000; // Sinon la pile par défaut ne suffit pas à la récurcivité
  51. #endif
  52.  
  53. extern const char *cmpversion; // Date et heure de compilation
  54.  
  55. struct _amsg amsg;  // Messages à afficher
  56. static string buff; // Source à interpréter
  57.  
  58. int calcligne( const char *ptr ){
  59. /* Renvoie le numéro de la ligne dans laquelle se trouve le pointeur
  60.  */
  61.     if(!ptr) return 0;
  62.  
  63.     int num=1;
  64.     register const char *x = buff.c_str();
  65.  
  66.     while( ptr > x && *x ){
  67.         if(*x=='\n') num++;
  68.         x++;
  69.     }
  70.     return num;
  71. }
  72.  
  73. int calchash( const char *s ){
  74. /*  Calcul le code hash pour la chaîne passée en argument.
  75.  *  La valeur retournée ne peut être NULLE.
  76.  */
  77.     register short int i=0;
  78.     register int val=0;
  79.  
  80.     for(;*s;i++,s++)
  81.         val += *s << (i % 4);
  82.  
  83.     return val?val:1;
  84. }
  85.  
  86. int main(const int ac, const char **av){
  87.     int pgm;
  88.     if(ac < 2){
  89.         cerr << "LFCInter 1.0 (" << cmpversion << "): Un interpréteur C...\n"
  90.            "\t© LFSoft 1995-96\nSyntaxe :\n\tLFCInter [options_LFCInter] Pgm_c [options_Pgm_c]\n"
  91.            "avec comme \"options_LFCInter\" :\n"
  92.            "   -un     : Affiche les remarques qu'une seule fois.\n"
  93.            "   -ncip   : Pas de remarque \"Conversion d'entier en pointeur\".\n"
  94.            "   -ncpi   : Pas de remarque \"Conversion de pointeur en entier\".\n"
  95.            "   -nprec  : Pas de remarque \"Perte de précision possible\".\n"
  96.            "   -tprec  : Test en temps réèl les pertes de précision.\n"
  97.            "   -fatal  : Test en temps réèl les pertes de précision lors de conversion ptr->int.\n"
  98.            "   -tnstd  : Affiche les opérations non-standard en C normal.\n"
  99.            "\n";
  100.         exit(5);
  101.     }
  102.  
  103.     for(pgm=1;pgm<ac;pgm++){
  104.         if(av[pgm][0] != '-') break; // Ce n'est plus une option
  105.         if(!strcmp(av[pgm],"-ncip"))
  106.             amsg.conv_int_ptr = false;
  107.         else if(!strcmp(av[pgm],"-ncpi"))
  108.             amsg.conv_ptr_int = false;
  109.         else if(!strcmp(av[pgm],"-nprec"))
  110.             amsg.perte_precis = false;
  111.         else if(!strcmp(av[pgm],"-tprec"))
  112.             amsg.rt_perte_prec = true;
  113.         else if(!strcmp(av[pgm],"-fatal"))
  114.             amsg.rt_fatal_ptr = true;
  115.         else if(!strcmp(av[pgm],"-un"))
  116.             amsg.wrn_1 = true;
  117.         else if(!strcmp(av[pgm],"-tnstd"))
  118.             amsg.conv_nstd = true;
  119.         else {
  120.             cerr << "Option \"" << av[pgm] << "\" inconnue : Tappez \"LFCInter\" pour la liste des options reconnues.\n";
  121.             exit(10);
  122.         }
  123.     }
  124.  
  125.     if(pgm==ac){
  126.         cerr << "*F* Le fichier source n'a pas été passé en argument.\n";
  127.         exit(10);
  128.     }
  129.  
  130.     DEB(cerr << "\n*D* Interprétation du fichier \"" << av[pgm] << "\".\n\n"; );
  131.  
  132.     ifstream src(av[pgm]);
  133.     if(!src){
  134.         cerr << "*F* Impossible d'ouvrir le fichier source\n";
  135.         exit(10);
  136.     }
  137.  
  138.     getline(src,buff,'\0'); // Lecture du fichier en entier (car un 0 ne peut pas se trouver dans un fichier ASCII)
  139.     src.close();
  140.  
  141.     _token ptr(buff.c_str()); // Lecture des symboles globaux
  142.     while(*ptr){
  143.         string id,type;
  144.         void *mem;
  145.  
  146.         if(lecdesc( ptr , id, type, 0, &mem)){
  147.             const char tbase = type[type.length()-1]; // Type de base de cette définition
  148.  
  149.             if(type[0] == 'F'){ // C'est une fonction
  150.                 if( *ptr == '{' /*}*/ ){
  151.                     ptr.saute(); // Saute le corps de la fonction
  152.                     ajoute_symbole(&tds_gbl,id,type,ptr,mem); // Création de l'objet dans la table des symboles
  153.                 } else
  154.                     cerr << "*R* Ligne " << calcligne(ptr) << ": Prototype de fonction ignoré.\n";
  155.             } else FOREVER {    // Autre chose qu'une fonction
  156.                 _var *variable = ajoute_symbole(&tds_gbl,id,type,ptr,mem); // Création de l'objet dans la table des symboles
  157.  
  158.                 if(*ptr == '='){ // Il y a une affectation immédiate...
  159.                     ptr++;
  160.                     VarAffecte(variable, eval(ptr,NULL,true),ptr);
  161.                 }
  162.  
  163.                 if(*ptr == ','){ // Autre déclaration
  164.                     ptr++;
  165.                     if(!lecdesc(ptr, id, type, tbase , &mem)){
  166.                         cerr << "*E* Ligne " << calcligne(ptr) << ": Erreur de syntaxe, une déclaration était attendue.\n";
  167.                         exit(5);
  168.                     }
  169.  
  170.                     if(type[0]=='F'){
  171.                         cerr << "*E* Ligne " << calcligne(ptr) << ": Une fonction ne peut être déclarée lors d'une définition multiple.\n";
  172.                         exit(5);
  173.                     }
  174.  
  175.                     // L'objet est ajouté à la table au début de la boucle
  176.                 } else if(*ptr == ';'){ // On a fini de lire cette déclaration
  177.                     ptr++;
  178.                     break;
  179.                 } else {
  180.                     cerr << "*E* Ligne " << calcligne(ptr) << ": Erreur de syntaxe" << ADEB("(main:1)" << ) ".\n";
  181.                     exit(5);
  182.                 }
  183.             }
  184.         } else if(*ptr == ';')
  185.             ptr++;
  186.         else if(*ptr){
  187.             cerr << "*E* Ligne " << calcligne(ptr) << ": Erreur de syntaxe, ';' était attendue. '"
  188.                  << ptr.obj() << "' lu\n";
  189.             exit(5);
  190.         }
  191.     }
  192.  
  193.     DEB(
  194.         cerr << "*D* Liste des symboles globaux:\n";
  195.         _var *smbl;
  196.         for(smbl=tds_gbl; smbl ; smbl = smbl->succ)
  197.             cerr << "*D*\t" << smbl->nom << ":" << smbl->type << "\n";
  198.     );
  199.  
  200.     LFDynaStack<_rep> arg;
  201.     arg.Push(_rep(ac-pgm)); // Pousse le nombre d'arguments
  202.     arg.Push(_rep((void *)(av + pgm),'*', string("*C"))); // Et les arguments eux-mêmes
  203.  
  204.     _var_fonc *fmain = (_var_fonc *)trouve_symbole(tds_gbl,string("main"));
  205.     if(!fmain){
  206.         cerr << "*E* Votre source ne contient pas de fonction main()\n";
  207.         exit(5);
  208.     }
  209.  
  210.     if(fmain->type[0] != 'F'){
  211.         cerr << "*E* Le symbole 'main' trouvé n'est pas une fonction.\n";
  212.         exit(5);
  213.     }
  214.  
  215.     if(fmain->type != "FI")
  216.         cerr << "*A* Ligne " << calcligne((const char *)fmain->val) << ": main() devrait renvoyer un entier.\n";
  217.  
  218.     execfonc(fmain,arg);
  219. }
  220.